<script>
  let activeEffect;

  class Dep {
    constructor(value) {
      this._value = value;
      this.subscribers = new Set();
    }
    addEffect() {
      if (!this.subscribers.has(activeEffect)) {
        this.subscribers.add(activeEffect);
      }
    }
    notify() {
      this.subscribers.forEach((effect) => {
        effect();
      });
    }
    get value() {
      if (activeEffect) {
        this.addEffect();
      }
      return this._value;
    }
    set value(newValue) {
      if (this._value === newValue) return;
      this._value = newValue;
      this.notify();
    }
  }

  function watchEffect(effect) {
    activeEffect = effect;
    try {
      effect();
    } finally {
      activeEffect = null;
    }
  }

  const dep = new Dep("hello");

  watchEffect(() => {
    console.log(dep.value);
  });

  setTimeout(() => {
    dep.value = "world";
  }, 1000);
</script>
